﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;

namespace NinjaToolbox
{
    public static class SubComponentUtil
    {
        public static Type[] GetChildrenClasses<T>()
        {
            return GetChildrenClasses(typeof(T));
        }

        public static Type[] GetChildrenClasses(Type type)
        {
            var result = new List<Type>();

            var assembly1 = Assembly.Load("Assembly-CSharp");
            var assembly2 = Assembly.Load("Assembly-CSharp-firstpass");
            var assembly3 = Assembly.Load("Assembly-CSharp-Editor");
            var assembly4 = Assembly.Load("Assembly-CSharp-Editor-firstpass");

            var assemblys = new Assembly[] { assembly1, assembly2, assembly3, assembly4 };

            for (int i = 0, iMax = assemblys.Length; i < iMax; i++)
            {
                var assembly = assemblys[i];
                var types = assembly.GetExportedTypes();

                var filterTypes = Array.FindAll(types, m => IsSubClassOf(m, type) && !m.IsGenericType && !m.IsAbstract);

                result.AddRange(filterTypes);
            }

            return result.ToArray();
        }

        public static object[] GetCustomAttributes(Type type, bool inhert = true)
        {
            var customAttributes = type.GetCustomAttributes(type, inhert);

            return customAttributes;
        }

        public static ATTRIBUTE_TYPE GetCustomAttribute<ATTRIBUTE_TYPE>(Type sourceType, bool inhert = true)
            where ATTRIBUTE_TYPE : class
        {
            return GetCustomAttribute(sourceType, typeof(ATTRIBUTE_TYPE), inhert) as ATTRIBUTE_TYPE;
        }

        public static object GetCustomAttribute(Type type, Type attributeType, bool inhert = true)
        {
            var customAttributes = type.GetCustomAttributes(attributeType, inhert);

            if (customAttributes != null && customAttributes.Length > 0) return customAttributes[0];

            return null;
        }

        static bool IsSubClassOf(Type type, Type baseType)
        {
            var b = type.BaseType;
            while (b != null)
            {
                if (b.Equals(baseType))
                {
                    return true;
                }
                b = b.BaseType;
            }
            return false;
        }
    }
}
